# 单纯的重复，不是迭代
"""
i = 0
while True:
    print(i)
"""
# 迭代是重复的过程，每一次重复都是基于上一次的结果而来
"""
l = ['a','b','c']
i = 0       # 循环变量
while i< len(l):        # 如果i<l列表的长度，则开始循环
    print(i)        # 打印循环变量（打印索引）
    print(l[i])     # 访问列表里每一个成员
    i+=1            # 循环变量+=1,每次让它+1，不然会有死循环
"""
# 列表，元组，字符串，字典
"""
print("==========")
t = (1,2,3)
i = 0
while i < len(t):
    print(t[i])
    i+=1
print("==========")
s = "abc"
i = 0
while i<len(s):
    print(s[i])
    i+=1
print("==========")
d = {"a":1,"b":2,"c":3}
i = 0
d_keys = list(d.keys())     # 获取所有key值
while i< len(d_keys):
    print(d_keys[i])
    i+=1
"""

# 可迭代对象：字符串，列表，集合，字典，元组

a = 1
# a.__iter__  # 整数类型不可以迭代
b = 1.1
# b.__iter__()    # 浮点型/小数不可以迭代
c = 'hello'
# c.__iter__()        # 字符串可以迭代
d = ['a','b']
# d.__iter__()        # 列表可以迭代
e = {1,2,3}
# e.__iter__()        # 集合可以迭代
f = {"a":1,"b":2}
# f.__iter__()        # 字典可以迭代
g = (1,2,3)
# g.__iter__()        # 元组可以迭代

# 迭代器
"""
__iter__()：创建迭代器
__next__()：取出下一次迭代的值
如果都取完啦，就会报错
"""
"""
dic = {'x':1,'y':2,'z':3}
iter_dic = dic.__iter__()  # 创建了一个迭代器对象
print(iter_dic.__next__())      # 访问下一个对象：x
print(iter_dic.__next__())      # 访问下一个对象：y
print(iter_dic.__next__())      # 访问下一个对象：z
print(iter_dic.__next__())      # 访问下一个对象：会报错，因为值已经取空啦
"""
# 误区
"""
list1 = [10,20,30]
print(list1.__iter__().__next__())  # 10
print(list1.__iter__().__next__())  # 10
print(list1.__iter__().__next__())  # 10
print(list1.__iter__().__next__())  # 10
print(list1.__iter__().__next__())  # 10
"""
"""
上面的代码块，一直都是新创建生成器，之后又直接拿下一个值
但是没有形成第二次的迭代
"""
dic1 = {'x':1,'y':2,'z':3}
iter_dic = dic1.__iter__()
# next 和__next__() 是一样的作用
"""
print(next(iter_dic))    # x
print(next(iter_dic))    # y
print(next(iter_dic))    # z
print(next(iter_dic))    # 报错
"""
# 为了解决这个问题，可以使用异常捕获进行
"""
while True:
    try:
        print(next(iter_dic))
    except StopIteration:       # 如果取空了
        break       # 停止循环
"""


# for 循环为什么和迭代器一起使用
"""
list1 = [10,20,30]
for i in list1:
    print(i)
"""
"""
for 循环做了两件事儿：
1 会把对象变为迭代器对象，可以迭代进行访问的
2 它会在最后一次迭代，做一个兜底（try except）捕捉异常，不会把报错信息展示给用户层面
"""

# 还记得range嘛
"""
obj_iter = range(1,10)
# print(obj_iter)
obj_next = obj_iter.__iter__()# 创建迭代器对象
print(next(obj_next)) # 1
print(next(obj_next)) # 2
print(next(obj_next)) # 3

# 问题
print("=============")
for i in obj_next:  # 遍历的是迭代器对象
    # 会从1开始还是从4开始？
    print(i)
print("===========")
for i in obj_next:
    print(i)
print("循环结束啦")

for i in obj_iter:      # obj_iter只是迭代对象，它不是迭代器，所以是可以随便拿的
    print(i)
"""
"""
迭代器：
每次迭代都是基于上一次的结果而来

iter和next组成了迭代器协议。iter可以创建迭代器对象，next可以访问下一次的值
可迭代的对象：字符串，列表，元组，集合，字典
"""

# 生成器
"""
生成器也是迭代器的一种
但是它只可以迭代一次
"""
# 下面的为啥可以迭代很多次；关键点在于while True 死循环
def gg():           # 定义函数
    a = 1           # 定义了局部变量a，初始值为1
    while True:     # 死循环
        yield a     # yield 关键字。这个是生成器。可以把它当成一个return
                    # 下次执行这个函数的时候，会从下向上执行，再走到yield里面
        a +=1       # 每次调用a+=1
a1 = gg()       # 调用函数，赋值
print(next(a1))     # 使用next访问下一次的值:1
print(next(a1))     # 2
print(next(a1))     # 3

